TerraformでControl Tower管理下のAWSアカウントを別のOUに移動する(AFTなし)
Control Tower管理下のAWSアカウントを別OUに移動する手順は、Control Tower管理外の環境と異なります。
今回はControl Tower管理下の既存のAWSアカウントをTerraformを使って、別OUに移動します。
前提
通常AWSアカウントのOU移動は、AWS Organizationsから変更可能です。
しかし、Control Tower管理下のAWSアカウントを別のOUに移動するには、AWS Service Catalogのプロビジョニングされた製品の設定を更新する必要があります。
今回は以下を想定しています。
- AWSアカウントをTerraformで管理している(
aws_organizations_account
) - IAM Identity Centerはセルフマネージド(AWS Control Towerで管理しない)
- AWS Control Towerを導入して、OU移動の方法を変更する必要がでてきた
- 対象のAWSアカウントはControl Tower管理下のOUに移動及びControl Towerへの登録も完了している
- 移動先のOUもControl Tower管理下のOU
Terraformでは以下の記述があるとします。
resource "aws_organizations_account" "sandbox" {
email = "sandbox@example.com"
name = "Sandbox"
parent_id = "ou-XXXXX"
}
やってみた
Control Tower管理下のAWSアカウントに対して、TerraformでOU移動をやってみます。
AWS Service Catalogプロビジョニングされた製品をTerraformにimportする
執筆時点(2024/7)でControl TowerのAPIでAWSアカウントのOUを変更するものは提供されていないため、AWS Service Catalogを操作します。
importするために、プロビジョニングされた製品のIDを確認します。現時点では、dataでIDを取得することができないため、コンソールから確認します。
「AWSマネジメントコンソール」 -> 「AWS Service Catalog」 -> 「プロビジョニング」 -> 「プロビジョニングされた製品」 の順に選択します。
ID列の値をコピーしておきます。
対象アカウントのAWS Service Catlogプロビジョニングされた製品をimportします。
import {
to = aws_servicecatalog_provisioned_product.sandbox
id = "pp-XXXXX" # 前の手順で取得したID
}
HCLを生成します。
terraform plan -generate-config-out=service_catlog.tf
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.
# __generated__ by Terraform from "pp-XXXXX"
resource "aws_servicecatalog_provisioned_product" "sandbox" {
accept_language = null
ignore_errors = null
name = "Enroll-Account-XXXXXX"
notification_arns = null
path_id = "lpv3-XXXXX"
path_name = null
product_id = "prod-XXXXX"
product_name = null
provisioning_artifact_id = "pa-XXXXX"
provisioning_artifact_name = null
retain_physical_resources = null
tags = {}
tags_all = {}
}
不要な引数を削除して、必要なパラメータを追加しました。
resource "aws_servicecatalog_provisioned_product" "sandbox1" {
name = "Enroll-Account-12345678901"
path_id = "lpv3-xxxxxx"
product_id = "prod-xxxxxxx"
provisioning_artifact_id = "pa-xxxxxxx"
provisioning_parameters {
key = "AccountName"
value = "AWS Team Masaki Sato Sandbox 1"
}
provisioning_parameters {
key = "AccountEmail"
value = "sandbox@example.com"
}
provisioning_parameters {
key = "ManagedOrganizationalUnit"
value = "ControlTowerTest1 (ou-XXXXXX)"
}
provisioning_parameters {
key = "SSOUserFirstName"
value = "NOT"
}
provisioning_parameters {
key = "SSOUserLastName"
value = "USE"
}
provisioning_parameters {
key = "SSOUserEmail"
value = "sandbox@example.com"
}
}
provisioning_parameters
で必要なパラメータは、Service Catalog -> 製品リスト -> 製品バージョンから確認できます。
AccountName
とAccountEmail
に使う値は、AWS Control Towerのコンソール上から確認できる情報で問題ありません。
ManagedOrganizationalUnit
はService CatalogのテンプレートのParameterでAlloedValuesで定義されているものを使ってください。(Organizations名 (OU ID)
の形式です。)
IAM Identity Center関連の以下のパラメータは、AWS Control TowerでIAM Identity Centerを管理している場合に利用されます。
- SSOUserFirstName
- SSOUserLastName
- SSOUserEmail
セルフマネージドの場合は、適当な値で問題ありません。値が無いと製品更新時にエラーになってしまうので、適当な値を入れています。
準備ができたらApplyします。
terraform plan
terraform apply
aws_organizations_account
のOUの引数をignore_changeに設定
前の手順でaws_servicecatalog_provisioned_product
でアカウントの所属先OUを管理しました。
aws_organizations_account
でも所属先OUを指定しており、2重管理になっています。
aws_organizations_account
側で所属先OUを変更しないように、ignore_changes
の記述を追加します。
resource "aws_organizations_account" "sandbox" {
email = "sandbox@example.com"
name = "Sandbox"
- parent_id = "ou-XXXXX"
+ lifecycle {
+ ignore_changes = [
+ parent_id
+ ]
+ }
}
変更による差分がでないことを確認します。
terraform plan
# 実行結果抜粋
No changes. Your infrastructure matches the configuration.
AWSアカウントの所属OUを変更する
最後に動作確認で、AWSアカウントの所属OUを変更してみます。
OUControlTowerTest1
にあるAWSアカウントAWS Team Masaki Sato Sandbox 1
をOUControlTowerTest2
に移動します。
provisioning_parameters
のkeyManagedOrganizationalUnit
を変更します。
resource "aws_servicecatalog_provisioned_product" "sandbox1" {
name = "Enroll-Account-12345678901"
path_id = "lpv3-xxxxxx"
product_id = "prod-xxxxxxx"
provisioning_artifact_id = "pa-xxxxxxx"
provisioning_parameters {
key = "AccountName"
value = "AWS Team Masaki Sato Sandbox 1"
}
provisioning_parameters {
key = "AccountEmail"
value = "sandbox@example.com"
}
provisioning_parameters {
key = "ManagedOrganizationalUnit"
+ value = "ControlTowerTest2 (ou-YYYYYY)"
- value = "ControlTowerTest1 (ou-XXXXXX)"
}
provisioning_parameters {
key = "SSOUserFirstName"
value = "NOT"
}
provisioning_parameters {
key = "SSOUserLastName"
value = "USE"
}
provisioning_parameters {
key = "SSOUserEmail"
value = "sandbox@example.com"
}
}
planを実行すると、パラメータが変更されることを確認できます。
terraform plan
# 抜粋
~ provisioning_parameters {
~ value = "ControlTowerTest1 (ou-XXXXXX)" -> "ControlTowerTest2 (ou-YYYYYYY)"
# (2 unchanged attributes hidden)
}
applyを実行して、変更を適用します。Service Catalogの更新に時間がかかるため、10分程度かかります。
terraform apply
マネジメントコンソールから、所属OUを変更できていることが確認できました。
Baseline stateも登録済み
になっているため、問題なさそうです。
おわりに
Control Tower管理下のAWSアカウントのOU移動をTerraformを使ってやってみました。
執筆時点(2024/7)は、Control Tower管理下のAWSアカウントのOU移動を直接行うAPIやAWS Providerの機能はありません。
そのため、Service Catalogを更新する方法となりました。
以下のIssueにある通り、Landing ZoneのAPI等は少し前に提供されていたので、今後追加される可能性はあると思います。追加されたら、直感的に定義できるようになるので楽しみですね。
ちなみにAFTだと以下のように、OUとアカウントを定義できます。AWS Control Tower + Terraformを利用している方は検討してみてください。
以上、AWS事業本部の佐藤(@chari7311)でした。